<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>光影穿梭</title>
    <style>
        html, body {
            margin: 0;
            padding: 0;
            background: #000;
            overflow: hidden;
            font-family: sans-serif;
        }
        canvas {
            display: block;
        }
        .controls {
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0,0,0,0.5);
            padding: 10px 20px;
            border-radius: 8px;
            color: #fff;
            user-select: none;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .btn {
            background: #00f;
            color: #fff;
            border: none;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            transition: background 0.2s;
        }
        .btn:hover {
            background: #00a;
        }
        .hud {
            position: fixed;
            top: 20px;
            left: 20px;
            color: #fff;
        }
        .message {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 32px;
            color: #fff;
            opacity: 0;
            pointer-events: none;
            text-align: center;
            transition: opacity 0.3s;
        }
        .message.show {
            opacity: 1;
        }
        .level-select {
            position: fixed;
            top: 70px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0,0,0,0.5);
            padding: 10px;
            border-radius: 8px;
            color: #fff;
        }
        .level-btn {
            background: #333;
            color: #fff;
            border: 1px solid #666;
            padding: 5px 10px;
            border-radius: 4px;
            cursor: pointer;
            margin: 0 2px;
            transition: all 0.2s;
        }
        .level-btn:hover {
            background: #555;
        }
        .level-btn.active {
            background: #00f;
            border-color: #00f;
        }
    </style>
</head>
<body>
    <div class="controls">
        角度: <span id="angle">0</span>°
        <button class="btn" id="fireBtn">发射</button>
        <button class="btn" id="nextBtn">下一关</button>
    </div>
    <div class="level-select">
        选择关卡: <span id="levelButtons"></span>
    </div>
    <div class="hud">
        关卡: <span id="level">1</span>
    </div>
    <div class="message" id="successMsg">成功！</div>
    <canvas id="canvas"></canvas>
    <script>
        let canvas = null, ctx = null;
        let W = window.innerWidth, H = window.innerHeight;
        let light = null, target = null;
        let lines = [];
        let isDragging = false;
        let currentLevel = 1;
        let maxReflections = 15; // 最大反射次数
        let totalLevels = 8; // 总关卡数
        
        // 关卡数据定义
        const levelData = [
            // 关卡1 - 简单反射
            {
                light: {x: 100, y: "center", angle: 0},
                target: {x: "right-100", y: "center", size: 10},
                lines: [
                    {x1: "center", y1: 100, x2: "center", y2: "bottom-100", color: "#fff"}
                ]
            },
            // 关卡2 - 直角反射
            {
                light: {x: 100, y: 100, angle: 0},
                target: {x: "right-100", y: "bottom-100", size: 10},
                lines: [
                    {x1: "center", y1: 100, x2: "center", y2: "bottom-100", color: "#fff"},
                    {x1: 100, y1: "center", x2: "right-100", y2: "center", color: "#fff"}
                ]
            },
            // 关卡3 - 吸收线
            {
                light: {x: 100, y: "center", angle: 0},
                target: {x: "right-100", y: "center", size: 10},
                lines: [
                    {x1: "1/3", y1: 100, x2: "1/3", y2: "bottom-100", color: "#fff"},
                    {x1: "2/3", y1: 100, x2: "2/3", y2: "bottom-100", color: "#fff"},
                    {x1: "1/3", y1: "center", x2: "2/3", y2: "center", color: "#f00"}
                ]
            },
            // 关卡4 - 双反射
            {
                light: {x: 100, y: 100, angle: 0},
                target: {x: "right-100", y: 100, size: 10},
                lines: [
                    {x1: "center", y1: 100, x2: "center", y2: "bottom-100", color: "#fff"},
                    {x1: 100, y1: "center", x2: "right-100", y2: "center", color: "#fff"}
                ]
            },
            // 关卡5 - 边缘反射
            {
                light: {x: 100, y: "center", angle: 0},
                target: {x: "right-100", y: "center", size: 10},
                lines: [
                    {x1: 200, y1: 200, x2: 400, y2: 400, color: "#fff"},
                    {x1: 200, y1: 400, x2: 400, y2: 200, color: "#fff"}
                ]
            },
            // 关卡6 - 复杂反射
            {
                light: {x: 100, y: 100, angle: 0},
                target: {x: "right-100", y: "bottom-100", size: 10},
                lines: [
                    {x1: 200, y1: 100, x2: 200, y2: "bottom-100", color: "#fff"},
                    {x1: 200, y1: 300, x2: "right-200", y2: 300, color: "#fff"},
                    {x1: "right-200", y1: 100, x2: "right-200", y2: "bottom-100", color: "#fff"}
                ]
            },
            // 关卡7 - 多反射
            {
                light: {x: 100, y: "center", angle: 0},
                target: {x: "right-100", y: "center", size: 10},
                lines: [
                    {x1: 200, y1: 100, x2: 200, y2: "bottom-100", color: "#fff"},
                    {x1: 400, y1: 100, x2: 400, y2: "bottom-100", color: "#fff"},
                    {x1: 600, y1: 100, x2: 600, y2: "bottom-100", color: "#fff"},
                    {x1: 200, y1: 200, x2: 600, y2: 200, color: "#fff"},
                    {x1: 200, y1: 400, x2: 600, y2: 400, color: "#fff"}
                ]
            },
            // 关卡8 - 终极挑战
            {
                light: {x: 100, y: 100, angle: 0},
                target: {x: "right-100", y: "bottom-100", size: 10},
                lines: [
                    {x1: 200, y1: 100, x2: 200, y2: "bottom-100", color: "#fff"},
                    {x1: 200, y1: 200, x2: "right-200", y2: 200, color: "#fff"},
                    {x1: "right-200", y1: 100, x2: "right-200", y2: "bottom-100", color: "#fff"},
                    {x1: 400, y1: 300, x2: 600, y2: 300, color: "#f00"},
                    {x1: 300, y1: 400, x2: 500, y2: 400, color: "#fff"}
                ]
            }
        ];
        
        function init () { 
            canvas = document.getElementById('canvas');
            ctx = canvas.getContext('2d');
            resizeCanvas();
            window.addEventListener('resize', resizeCanvas);
            
            // 创建关卡选择按钮
            createLevelButtons();
            
            // 初始化关卡
            initLevel(currentLevel);
            
            // 事件监听
            canvas.addEventListener('mousedown', startDrag);
            canvas.addEventListener('mousemove', drag);
            canvas.addEventListener('mouseup', endDrag);
            canvas.addEventListener('mouseleave', endDrag);
            
            document.getElementById('fireBtn').addEventListener('click', fireLight);
            document.getElementById('nextBtn').addEventListener('click', nextLevel);
        }
        
        function createLevelButtons() {
            const container = document.getElementById('levelButtons');
            container.innerHTML = '';
            
            for (let i = 1; i <= totalLevels; i++) {
                const btn = document.createElement('button');
                btn.className = 'level-btn' + (i === currentLevel ? ' active' : '');
                btn.textContent = i;
                btn.addEventListener('click', () => {
                    currentLevel = i;
                    updateLevelButtons();
                    initLevel(currentLevel);
                });
                container.appendChild(btn);
            }
        }
        
        function updateLevelButtons() {
            const buttons = document.querySelectorAll('.level-btn');
            buttons.forEach((btn, index) => {
                if (index + 1 === currentLevel) {
                    btn.classList.add('active');
                } else {
                    btn.classList.remove('active');
                }
            });
        }
        
        function resizeCanvas() {
            W = window.innerWidth;
            H = window.innerHeight;
            canvas.width = W;
            canvas.height = H;
            // 只有在游戏元素初始化后才重新初始化关卡
            if (light && target && lines.length > 0) {
                initLevel(currentLevel);
            }
        }
        
        // 解析位置值，可以是数字、"center"、"right-100"、"bottom-100"、"1/3"、"2/3"等
        function parsePosition(value, axis) {
            const size = axis === 'x' ? W : H;
            
            if (typeof value === 'number') return value;
            if (typeof value === 'string') {
                if (value === 'center') return size / 2;
                if (value.startsWith('right-')) return size - parseInt(value.substring(6));
                if (value.startsWith('left-')) return parseInt(value.substring(5));
                if (value.startsWith('bottom-')) return size - parseInt(value.substring(7));
                if (value.startsWith('top-')) return parseInt(value.substring(4));
                if (value.includes('/')) {
                    const parts = value.split('/');
                    return size * (parseInt(parts[0]) / parseInt(parts[1]));
                }
            }
            return 0;
        }
        
        function initLevel(level) {
            if (level < 1 || level > totalLevels) return;
            
            lines = [];
            const data = levelData[level - 1];
            
            // 初始化光源
            light = new Light({
                x: parsePosition(data.light.x, 'x'),
                y: parsePosition(data.light.y, 'y'),
                angle: data.light.angle || 0
            });
            
            // 初始化目标
            target = new Target({
                x: parsePosition(data.target.x, 'x'),
                y: parsePosition(data.target.y, 'y'),
                size: data.target.size || 10
            });
            
            // 初始化线条
            data.lines.forEach(line => {
                lines.push(new Line({
                    x1: parsePosition(line.x1, 'x'),
                    y1: parsePosition(line.y1, 'y'),
                    x2: parsePosition(line.x2, 'x'),
                    y2: parsePosition(line.y2, 'y'),
                    color: line.color || '#fff'
                }));
            });
            
            document.getElementById('level').textContent = currentLevel;
            updateLevelButtons();
            drawScene();
        }
        
        function drawScene() {
            if (!ctx || !light || !target) return;
            
            ctx.clearRect(0, 0, W, H);
            
            // 绘制所有线条
            lines.forEach(line => line.draw());
            
            // 绘制光源和目标
            light.draw();
            target.draw();
        }
        
        function startDrag(e) {
            const rect = canvas.getBoundingClientRect();
            const x = e.clientX - rect.left;
            const y = e.clientY - rect.top;
            
            // 检查是否点击了光源
            const dx = x - light.x;
            const dy = y - light.y;
            if (Math.sqrt(dx*dx + dy*dy) <= 15) {
                isDragging = true;
            }
        }
        
        function drag(e) {
            if (!isDragging) return;
            
            const rect = canvas.getBoundingClientRect();
            const x = e.clientX - rect.left;
            const y = e.clientY - rect.top;
            
            // 计算新角度 (从光源指向鼠标位置)
            const dx = x - light.x;
            const dy = y - light.y;
            light.angle = Math.atan2(dy, dx);
            
            // 更新角度显示
            document.getElementById('angle').textContent = Math.round(light.angle * 180 / Math.PI);
            
            drawScene();
        }
        
        function endDrag() {
            isDragging = false;
        }
        
        // 线段与圆相交检测
        function lineIntersectsCircle(x1, y1, x2, y2, cx, cy, r) {
            const dx = cx - x1;
            const dy = cy - y1;
            const a = x2 - x1;
            const b = y2 - y1;
            const len2 = a*a + b*b;
            if (len2 === 0) return Math.hypot(dx, dy) <= r; // 线段长度为0
            
            let t = (dx*a + dy*b) / len2;
            t = Math.max(0, Math.min(1, t));
            const nearestX = x1 + t*a;
            const nearestY = y1 + t*b;
            const dist2 = Math.pow(nearestX - cx, 2) + Math.pow(nearestY - cy, 2);
            return dist2 <= r*r;
        }
        
        function fireLight() {
            if (!light || !target) return;
            
            ctx.clearRect(0, 0, W, H);
            lines.forEach(line => line.draw());
            light.draw();
            target.draw();
            
            let x = light.x;
            let y = light.y;
            let dx = Math.cos(light.angle);
            let dy = Math.sin(light.angle);
            let reflections = 0;
            
            while (reflections <= maxReflections) {
                // 检查当前光线段是否经过目标
                if (lineIntersectsCircle(x, y, x + dx * 1000, y + dy * 1000, target.x, target.y, target.size)) {
                    ctx.beginPath();
                    ctx.moveTo(x, y);
                    ctx.lineTo(target.x, target.y);
                    ctx.strokeStyle = '#0f0';
                    ctx.lineWidth = 2;
                    ctx.stroke();
                    showSuccessMessage();
                    return;
                }
                
                let minDist = Infinity;
                let hitLine = null;
                let hitX = x, hitY = y;
                let hitType = 'line';
                
                // 检查与障碍物线条的碰撞
                lines.forEach(line => {
                    const intersection = getLineIntersection(x, y, x + dx * 1000, y + dy * 1000, line.x1, line.y1, line.x2, line.y2);
                    if (intersection) {
                        const dist = Math.hypot(intersection.x - x, intersection.y - y);
                        if (dist > 0 && dist < minDist) {
                            minDist = dist;
                            hitLine = line;
                            hitX = intersection.x;
                            hitY = intersection.y;
                            hitType = 'line';
                        }
                    }
                });
                
                // 检查与屏幕边缘的碰撞
                const edgeIntersection = getEdgeIntersection(x, y, dx, dy);
                if (edgeIntersection) {
                    const dist = Math.hypot(edgeIntersection.x - x, edgeIntersection.y - y);
                    if (dist > 0 && dist < minDist) {
                        minDist = dist;
                        hitX = edgeIntersection.x;
                        hitY = edgeIntersection.y;
                        hitType = 'edge';
                        hitLine = edgeIntersection.edge;
                    }
                }
                
                if (!hitLine) break;
                
                // 绘制到交点
                ctx.beginPath();
                ctx.moveTo(x, y);
                ctx.lineTo(hitX, hitY);
                ctx.strokeStyle = '#0f0';
                ctx.lineWidth = 2;
                ctx.stroke();
                
                // 处理碰撞
                if (hitType === 'line') {
                    // 检查击中的线条颜色
                    if (hitLine.color === '#f00') {
                        // 红线吸收光线，结束
                        break;
                    }
                    
                    // 计算在物体上的反射角度
                    const nx = hitLine.y1 - hitLine.y2;
                    const ny = hitLine.x2 - hitLine.x1;
                    const len = Math.sqrt(nx*nx + ny*ny);
                    const normX = nx / len;
                    const normY = ny / len;
                    
                    const dot = dx * normX + dy * normY;
                    dx = dx - 2 * dot * normX;
                    dy = dy - 2 * dot * normY;
                } else if (hitType === 'edge') {
                    // 计算在屏幕边缘的反射角度
                    if (hitLine === 'left' || hitLine === 'right') {
                        // 左右边缘反射，x方向反转
                        dx = -dx;
                    } else {
                        // 上下边缘反射，y方向反转
                        dy = -dy;
                    }
                }
                
                // 更新光线位置
                x = hitX;
                y = hitY;
                
                reflections++;
            }
        }
        
        // 计算光线与屏幕边缘的交点
        function getEdgeIntersection(x, y, dx, dy) {
            let edgeX, edgeY, edge;
            let tMin = Infinity;
            
            // 计算与左右边缘的交点
            if (dx !== 0) {
                const tLeft = (-x) / dx;
                const tRight = (W - x) / dx;
                
                if (tLeft > 0 && tLeft < tMin) {
                    tMin = tLeft;
                    edgeX = 0;
                    edgeY = y + dy * tLeft;
                    edge = 'left';
                }
                if (tRight > 0 && tRight < tMin) {
                    tMin = tRight;
                    edgeX = W;
                    edgeY = y + dy * tRight;
                    edge = 'right';
                }
            }
            
            // 计算与上下边缘的交点
            if (dy !== 0) {
                const tTop = (-y) / dy;
                const tBottom = (H - y) / dy;
                
                if (tTop > 0 && tTop < tMin) {
                    tMin = tTop;
                    edgeX = x + dx * tTop;
                    edgeY = 0;
                    edge = 'top';
                }
                if (tBottom > 0 && tBottom < tMin) {
                    tMin = tBottom;
                    edgeX = x + dx * tBottom;
                    edgeY = H;
                    edge = 'bottom';
                }
            }
            
            if (edgeX !== undefined) {
                return {x: edgeX, y: edgeY, edge: edge};
            }
            
            return null;
        }
        
        function showSuccessMessage() {
            const msg = document.getElementById('successMsg');
            msg.classList.add('show');
            setTimeout(() => {
                msg.classList.remove('show');
            }, 2000);
        }
        
        function nextLevel() {
            currentLevel++;
            if (currentLevel > totalLevels) {
                currentLevel = 1; // 循环回到第一关
            }
            initLevel(currentLevel);
        }
        
        function getLineIntersection(x1, y1, x2, y2, x3, y3, x4, y4) {
            const denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
            if (denom === 0) return null; // 平行线
            
            const ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
            const ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;
            
            if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {
                const x = x1 + ua * (x2 - x1);
                const y = y1 + ua * (y2 - y1);
                return {x, y};
            }
            
            return null;
        }
        
        class Light{
            constructor({x, y, angle}) {
                this.x = x;
                this.y = y;
                this.angle = angle;
                this.color = '#ff0';
            }
            draw() {
                ctx.beginPath();
                ctx.arc(this.x, this.y, 10, 0, Math.PI * 2);
                ctx.fillStyle = this.color;
                ctx.fill();
                
                // 绘制光线方向指示
                ctx.beginPath();
                ctx.moveTo(this.x, this.y);
                ctx.lineTo(
                    this.x + Math.cos(this.angle) * 30,
                    this.y + Math.sin(this.angle) * 30
                );
                ctx.strokeStyle = this.color;
                ctx.lineWidth = 2;
                ctx.stroke();
            }
        }
        
        class Target{
            constructor({x, y, size}) {
                this.x = x;
                this.y = y;
                this.size = size || 10;
                this.color = '#f00';
            }
            draw() {
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.fillStyle = this.color;
                ctx.fill();
                
                // 添加脉动效果
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size + 5, 0, Math.PI * 2);
                ctx.strokeStyle = this.color;
                ctx.lineWidth = 1;
                ctx.stroke();
            }
        }
        
        class Line{
            constructor({x1, y1, x2, y2, color}) {
                this.x1 = x1;
                this.y1 = y1;
                this.x2 = x2;
                this.y2 = y2;
                this.color = color || '#fff';
            }
            draw() {
                ctx.beginPath();
                ctx.moveTo(this.x1, this.y1);
                ctx.lineTo(this.x2, this.y2);
                ctx.strokeStyle = this.color;
                ctx.lineWidth = 2;
                ctx.stroke();
            }
        }
        
        init();
    </script>
</body>
</html>